04-데이터베이스연동

데이터베이스 연동 (Tomcat + RDS)

WAS 서버에서 RDS MySQL 데이터베이스에 연결하여 완전한 3-Tier 아키텍처를 완성합니다.

전제조건

1. MySQL 드라이버 설치

WAS 서버에서 MySQL에 연결하기 위한 드라이버를 설치합니다.

WAS 서버 접속

# Web 서버 → WAS 서버로 접속
ssh -i webapp-keypair.pem ec2-user@[Web서버-Public-IP]
ssh ec2-user@[WAS서버-Private-IP]

MySQL 드라이버 다운로드

# MySQL Connector 다운로드
cd /tmp
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-8.0.33.tar.gz

# 압축 해제
tar -xzf mysql-connector-j-8.0.33.tar.gz

# Tomcat lib 디렉토리로 복사
sudo cp mysql-connector-j-8.0.33/mysql-connector-j-8.0.33.jar /opt/tomcat/lib/

# 소유권 설정
sudo chown tomcat:tomcat /opt/tomcat/lib/mysql-connector-j-8.0.33.jar

Pasted image 20250904174856.png

2. 환경 변수 설정

DB 연결 정보를 환경 변수로 설정합니다.

RDS 연결 정보 설정

# RDS 연결 정보 환경 변수 설정 (실제 엔드포인트로 교체!)
export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
export DB_USER="admin"
export DB_PASSWORD="webapp123!"
export DB_NAME="webapp_db"

# 영구 설정
echo 'export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"' | sudo tee -a /etc/environment
echo 'export DB_USER="admin"' | sudo tee -a /etc/environment
echo 'export DB_PASSWORD="webapp123!"' | sudo tee -a /etc/environment
echo 'export DB_NAME="webapp_db"' | sudo tee -a /etc/environment

# 설정 확인
echo "DB_HOST: $DB_HOST"
echo "DB_USER: $DB_USER"
echo "DB_NAME: $DB_NAME"

DB 연결 테스트

# MySQL 클라이언트 설치 (없는 경우)
sudo yum update -y 
sudo yum install mariadb105 -y

# DB 연결 테스트
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME

# 연결되면 다음 명령어로 테스트:
# SHOW TABLES;
# SELECT * FROM users;
# quit

3. 데이터베이스 연동 JSP 페이지 생성

간단한 JSP로 사용자 등록/조회 기능을 만듭니다.

DB 연동 메인 페이지

# 기존 index.jsp를 DB 연동 버전으로 교체
sudo tee /opt/tomcat/webapps/webapp/index.jsp << 'EOF'
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.sql.*, java.util.*" %>
<%
    // DB 연결 정보
    String dbHost = System.getenv("DB_HOST");
    String dbUser = System.getenv("DB_USER");  
    String dbPassword = System.getenv("DB_PASSWORD");
    String dbName = System.getenv("DB_NAME");
    String dbUrl = "jdbc:mysql://" + dbHost + ":3306/" + dbName;
    
    Connection conn = null;
    String message = "";
    List<Map<String, String>> users = new ArrayList<>();
    
    try {
        // MySQL 드라이버 로드
        Class.forName("com.mysql.cj.jdbc.Driver");
        conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
        
        // 사용자 등록 처리
        if (request.getMethod().equals("POST")) {
            String name = request.getParameter("name");
            String email = request.getParameter("email");
            
            if (name != null && email != null && !name.trim().isEmpty() && !email.trim().isEmpty()) {
                String insertSql = "INSERT INTO users (name, email) VALUES (?, ?)";
                PreparedStatement pstmt = conn.prepareStatement(insertSql);
                pstmt.setString(1, name.trim());
                pstmt.setString(2, email.trim());
                
                int result = pstmt.executeUpdate();
                if (result > 0) {
                    message = "사용자가 성공적으로 등록되었습니다!";
                } else {
                    message = "등록에 실패했습니다.";
                }
                pstmt.close();
            }
        }
        
        // 사용자 목록 조회
        String selectSql = "SELECT id, name, email, created_at FROM users ORDER BY created_at DESC";
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery(selectSql);
        
        while (rs.next()) {
            Map<String, String> user = new HashMap<>();
            user.put("id", rs.getString("id"));
            user.put("name", rs.getString("name"));
            user.put("email", rs.getString("email"));
            user.put("created_at", rs.getString("created_at"));
            users.add(user);
        }
        
        rs.close();
        stmt.close();
        
    } catch (Exception e) {
        message = "데이터베이스 오류: " + e.getMessage();
        e.printStackTrace();
    } finally {
        if (conn != null) {
            try { conn.close(); } catch (SQLException e) {}
        }
    }
%>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web/WAS/DB 3-Tier 아키텍처</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        .container {
            max-width: 900px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            overflow: hidden;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        }
        header {
            background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
            color: white;
            padding: 2rem;
            text-align: center;
        }
        header h1 {
            font-size: 2rem;
            margin-bottom: 0.5rem;
        }
        main {
            padding: 2rem;
        }
        .section {
            margin-bottom: 2rem;
            padding: 1.5rem;
            background: #f8f9fa;
            border-radius: 8px;
            border-left: 4px solid #4ECDC4;
        }
        .form-group {
            margin-bottom: 1rem;
        }
        label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: bold;
        }
        input[type="text"], input[type="email"] {
            width: 100%;
            padding: 0.5rem;
            border: 1px solid #ddd;
            border-radius: 4px;
        }
        button {
            background: linear-gradient(45deg, #FF6B6B, #4ECDC4);
            color: white;
            padding: 0.75rem 1.5rem;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }
        button:hover {
            opacity: 0.9;
        }
        .message {
            padding: 1rem;
            background: #d4edda;
            color: #155724;
            border-radius: 4px;
            margin-bottom: 1rem;
        }
        .user-item {
            background: white;
            padding: 1rem;
            margin-bottom: 0.5rem;
            border-radius: 4px;
            border-left: 3px solid #4ECDC4;
        }
        .architecture {
            text-align: center;
            background: #e3f2fd;
            padding: 1rem;
            border-radius: 4px;
            margin-bottom: 1rem;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1> Web/WAS/DB 3-Tier 아키텍처</h1>
            <p>Apache → Tomcat → MySQL RDS</p>
        </header>

        <main>
            <div class="architecture">
                <strong>현재 처리 경로:</strong><br>
                브라우저 → Apache HTTP Server → Tomcat WAS → RDS MySQL
            </div>

            <% if (!message.isEmpty()) { %>
            <div class="message"><%= message %></div>
            <% } %>

            <div class="section">
                <h2>새 사용자 등록</h2>
                <form method="post">
                    <div class="form-group">
                        <label for="name">이름:</label>
                        <input type="text" id="name" name="name" required>
                    </div>
                    <div class="form-group">
                        <label for="email">이메일:</label>
                        <input type="email" id="email" name="email" required>
                    </div>
                    <button type="submit">등록하기</button>
                </form>
            </div>

            <div class="section">
                <h2>등록된 사용자 목록 (<%= users.size() %>명)</h2>
                <% if (users.isEmpty()) { %>
                    <p>등록된 사용자가 없습니다.</p>
                <% } else { %>
                    <% for (Map<String, String> user : users) { %>
                    <div class="user-item">
                        <strong><%= user.get("name") %></strong><br>
                        이메일: <%= user.get("email") %><br>
                        <small>등록일: <%= user.get("created_at") %></small>
                    </div>
                    <% } %>
                <% } %>
            </div>
        </main>

        <footer style="background: #333; color: white; text-align: center; padding: 1rem;">
            <p>AWS EDU Week2 심화실습 - 완전한 3-Tier 아키텍처</p>
        </footer>
    </div>
</body>
</html>
EOF

4. Tomcat 재시작

환경 변수와 새로운 코드를 적용하기 위해 Tomcat을 재시작합니다.

서비스 재시작

# Tomcat 재시작
sudo systemctl restart tomcat

# 서비스 상태 확인
sudo systemctl status tomcat

# 로그 확인
sudo tail -f /opt/tomcat/logs/catalina.out

5. 전체 시스템 테스트

완전한 3-Tier 아키텍처를 테스트합니다.

브라우저 테스트

  1. Web 서버를 통한 접속:

    • URL: http://[Web서버-Public-IP]/webapp/
    • 처리 경로: 브라우저 → Apache → Tomcat → RDS → Tomcat → Apache → 브라우저
  2. 사용자 등록 테스트:

  3. 데이터 확인:

    • 등록된 사용자가 목록에 표시되는지 확인
    • 페이지 새로고침 시 데이터가 유지되는지 확인

명령어 테스트

# Web 서버에서 테스트
curl http://localhost/webapp/

# HTML 응답에 사용자 목록이 포함되어 있으면 성공

데이터베이스 직접 확인

# 실제로 DB에 데이터가 저장되었는지 확인
mysql -h $DB_HOST -u $DB_USER -p$DB_PASSWORD $DB_NAME

# MySQL에서 실행:
# SELECT * FROM users ORDER BY created_at DESC LIMIT 5;
# quit

6. 아키텍처 완성도 확인

3-Tier 처리 흐름 검증

  1. Presentation Tier (Web): Apache HTTP Server

    • 정적 파일 처리
    • 프록시 역할
  2. Application Tier (WAS): Tomcat

    • JSP 처리
    • 비즈니스 로직
    • DB 연결
  3. Data Tier (DB): RDS MySQL

    • 데이터 저장/조회
    • 트랜잭션 처리

성능 및 확장성

# 동시 처리 테스트 (간단한 부하 테스트)
for i in {1..5}; do
  curl -s http://localhost/webapp/ > /dev/null &
done
wait

echo "동시 요청 처리 완료"

완료 체크리스트

아키텍처 완성

최종 시스템 구조

사용자
  ↓ HTTP 요청
Apache HTTP Server (Public 서브넷)
  ↓ 프록시 (동적 요청만)
Tomcat WAS (Private 서브넷)  
  ↓ SQL 쿼리
RDS MySQL (Private 서브넷)
  ↓ 결과
Tomcat WAS
  ↓ HTML 응답
Apache HTTP Server
  ↓ HTTP 응답  
사용자

분리된 역할


3-Tier 아키텍처 구축 완료!

Web/WAS/DB가 완전히 분리된 확장 가능하고 안전한 시스템이 완성되었습니다. 이제 각 계층을 독립적으로 확장하거나 관리할 수 있습니다.

7. 트러블슈팅

환경변수 관련 문제

문제: DB 연결 실패 - 환경변수를 읽어오지 못함

# 현재 설정된 환경변수 확인
echo "DB_HOST: $DB_HOST"
echo "DB_USER: $DB_USER"
echo "DB_PASSWORD: $DB_PASSWORD"
echo "DB_NAME: $DB_NAME"

해결방법 1: Tomcat 서비스 파일에 환경변수 직접 추가

# Tomcat systemd 서비스 파일 편집
sudo systemctl edit tomcat

# 다음 내용 추가:
[Service]
Environment="DB_HOST=your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
Environment="DB_USER=admin"
Environment="DB_PASSWORD=webapp123!"
Environment="DB_NAME=webapp_db"

# 서비스 재시작
sudo systemctl daemon-reload
sudo systemctl restart tomcat

해결방법 2: Tomcat 시작 스크립트에 환경변수 설정

# setenv.sh 파일 생성
sudo tee /opt/tomcat/bin/setenv.sh << 'EOF'
export DB_HOST="your-rds-endpoint.cx6mc24eklg5.ap-northeast-3.rds.amazonaws.com"
export DB_USER="admin"
export DB_PASSWORD="webapp123!"
export DB_NAME="webapp_db"
EOF

# 실행권한 부여
sudo chmod +x /opt/tomcat/bin/setenv.sh
sudo chown tomcat:tomcat /opt/tomcat/bin/setenv.sh

# Tomcat 재시작
sudo systemctl restart tomcat

문제: 환경변수는 설정되었지만 JSP에서 null 값 반환

# JSP에서 디버깅용 코드 임시 추가
<%
out.println("DB_HOST from env: " + System.getenv("DB_HOST"));
out.println("DB_USER from env: " + System.getenv("DB_USER"));
%>

해결방법: context.xml에 환경변수를 리소스로 등록

# Tomcat context.xml 편집
sudo vi /opt/tomcat/conf/context.xml

# <Context> 태그 안에 추가:
<Environment name="DB_HOST" type="java.lang.String" value="your-rds-endpoint" />
<Environment name="DB_USER" type="java.lang.String" value="admin" />
<Environment name="DB_PASSWORD" type="java.lang.String" value="webapp123!" />
<Environment name="DB_NAME" type="java.lang.String" value="webapp_db" />

# JSP에서 JNDI로 접근:
<%
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
String dbHost = (String)envContext.lookup("DB_HOST");
%>

네트워크 연결 문제

문제: 타임아웃 에러로 RDS 연결 실패

# 네트워크 연결 테스트
telnet $DB_HOST 3306

# 보안그룹 확인 (AWS CLI 필요)
aws ec2 describe-security-groups --group-names rds-security-group

해결방법: 보안그룹 설정 확인 및 수정

  1. RDS 보안그룹에서 WAS 서버 보안그룹으로부터 포트 3306 허용 확인
  2. WAS 서버 보안그룹에서 아웃바운드 3306 포트 허용 확인
  3. 서브넷 라우팅 테이블 확인

MySQL 드라이버 문제

문제: ClassNotFoundException - MySQL 드라이버를 찾을 수 없음

# 드라이버 파일 존재 확인
ls -la /opt/tomcat/lib/mysql-connector-j*.jar

# 파일 권한 확인
stat /opt/tomcat/lib/mysql-connector-j*.jar

해결방법: 드라이버 재설치 및 권한 수정

# 기존 드라이버 삭제 후 재설치
sudo rm -f /opt/tomcat/lib/mysql-connector-j*.jar

# 최신 버전 다운로드
cd /tmp
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-j-8.2.0.tar.gz
tar -xzf mysql-connector-j-8.2.0.tar.gz
sudo cp mysql-connector-j-8.2.0/mysql-connector-j-8.2.0.jar /opt/tomcat/lib/

# 올바른 권한 설정
sudo chown tomcat:tomcat /opt/tomcat/lib/mysql-connector-j-8.2.0.jar
sudo chmod 644 /opt/tomcat/lib/mysql-connector-j-8.2.0.jar

# Tomcat 재시작
sudo systemctl restart tomcat

메모리 부족 문제

문제: OutOfMemoryError 발생

# 현재 메모리 사용량 확인
free -h
top -p $(pgrep -f tomcat)

해결방법: Tomcat 메모리 설정 조정

# setenv.sh에 메모리 옵션 추가
echo 'export CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=512m"' | sudo tee -a /opt/tomcat/bin/setenv.sh

# Tomcat 재시작
sudo systemctl restart tomcat

관련 문서: AWS EDU/Archive/조선대학교 AWS 멘토링/Week2-Dynamic-WebApp-Deployment/Week2-전체가이드, AWS EDU/Archive/조선대학교 AWS 멘토링/Week3-WAS-Deployment/WebWAS분리/03-Web서버연동